package org.tinygroup.xmlsignature.impl;


import java.security.*;
import java.util.*;

import java.security.cert.CertificateFactory;
import java.security.cert.Certificate;

import org.tinygroup.commons.tools.StringUtil;
import org.tinygroup.vfs.FileObject;
import org.tinygroup.vfs.VFS;
import org.tinygroup.xmlsignature.XmlSignatureManager;
import org.tinygroup.xmlsignature.config.XmlSignatureConfig;
import org.tinygroup.xmlsignature.config.XmlSignatureConfigs;

/**
 * 默认的XML数字签名配置管理器
 * @author yancheng11334
 *
 */
public class DefaultXmlSignatureManager implements XmlSignatureManager{

	private Map<String,XmlSignatureConfig> configMaps = new HashMap<String,XmlSignatureConfig>();
	private Map<String,KeyPair> keyPairMaps = new HashMap<String,KeyPair>();
	
	public void addXmlSignatureConfig(XmlSignatureConfig config) {
		if(config!=null){
		   configMaps.put(config.getUserId(), config);
		}
	}

	public void removeXmlSignatureConfig(String userId) {
		configMaps.remove(userId);
		keyPairMaps.remove(userId);
	}

	public XmlSignatureConfig getXmlSignatureConfig(String userId) {
		return configMaps.get(userId);
	}

	public void addXmlSignatureConfigs(XmlSignatureConfigs configs) {
		if(configs!=null && configs.getXmlSignatureConfigList()!=null){
		   for(XmlSignatureConfig config:configs.getXmlSignatureConfigList()){
			   addXmlSignatureConfig(config);
		   }
		}
	}

	public void removeXmlSignatureConfigs(XmlSignatureConfigs configs) {
		if(configs!=null && configs.getXmlSignatureConfigList()!=null){
			for(XmlSignatureConfig config:configs.getXmlSignatureConfigList()){
			    removeXmlSignatureConfig(config.getUserId());
			}
		}
	}

	public KeyPair getKeyPair(String userId) {
		//如果存在KeyPair,直接返回
		KeyPair keyPair = keyPairMaps.get(userId);
		if(keyPair!=null){
		   return keyPair;
		}
		
		XmlSignatureConfig config = configMaps.get(userId);
		if(config!=null){
		   //创建keyPair
		   keyPair = loadKeyPair(config);
		   keyPairMaps.put(userId, keyPair);
		   return keyPair;
		}
		return null;
	}
	
	//根据PublicKey和PrivateKey创建密钥对
	private KeyPair loadKeyPair(XmlSignatureConfig config){
		try{
			PrivateKey privateKey = loadPrivateKey(config);
			PublicKey  publicKey = loadPublicKey(config);
			return new KeyPair(publicKey,privateKey);
		}catch(Exception e){
			throw new RuntimeException(String.format("根据配置项[%s]生成KeyPair失败", config.toString()),e);
		}
	}
	
	//装载公钥
	private PublicKey loadPublicKey(XmlSignatureConfig config) throws Exception{
		String storeType = StringUtil.isEmpty(config.getPublicStoreType())?"X.509":config.getPublicStoreType();
		CertificateFactory cf = CertificateFactory.getInstance(storeType);
		FileObject file = VFS.resolveFile(config.getPublicKeyPath());
		Certificate c = cf.generateCertificate(file.getInputStream());
		return c.getPublicKey();
	}
	
	//装载私钥
	private PrivateKey loadPrivateKey(XmlSignatureConfig config) throws Exception{
		String storeType = StringUtil.isEmpty(config.getPrivateStoreType())?KeyStore.getDefaultType():config.getPrivateStoreType();
		KeyStore keyStore = KeyStore.getInstance(storeType);
		FileObject file = VFS.resolveFile(config.getPrivateKeyPath());
		char[] password = config.getPassword().toCharArray();
		keyStore.load(file.getInputStream(),password);
		return (PrivateKey) keyStore.getKey(config.getAlias(), password);
	}

}
